<?php

namespace App\Service;

use App\Constants\ErrorCode;
use App\Library\Common;
use App\Model\data\CurrentShopData;
use App\Model\DeliveryRule;
use App\Model\DeliveryRuleArea;
use App\Model\DeliverySendOrder;
use App\Model\DeliverySendOrderLog;
use Hyperf\DbConnection\Db;
use App\Model\DeliveryTpl;
use App\Model\FlyOrder;
use App\Model\FlyShopBalance;
use App\Model\FlyShopDelivery;
use App\Model\PollLog;
use Hyperf\Redis\Redis;
use Hyperf\Snowflake\IdGeneratorInterface;
use Hyperf\Utils\ApplicationContext;
use PhpParser\Node\Expr\New_;
use Psr\Container\ContainerInterface;
use Hyperf\Di\Annotation\Inject;
use Swoole\Exception;

class DeliverySendService extends BaseService
{
    /**
     * @Inject
     * @var ShopSendAddressService
     */
    private $sendAddr;

    const DELIVERY=[
        'yuantong'=>'圆通速递',
        'yunda'=>'韵达快递',
        'zhongtong'=>'中通快递',
        'shentong'=>'申通快递',
        'jtexpress'=>'极兔速递',
        'shunfeng'=>'顺丰速运',
        'jd'=>'京东物流',
        'youzhengguonei'=>'邮政快递包裹',
        'debangkuaidi'=>'德邦快递',
        'ems'=>'EMS',
    ];


    protected $key;   // 账户key
    protected $secret;  // 账户secret
    protected $secret_key;  // 客户授权$secret_key
    protected $order_code;  // 下单secret_code;
    protected $cancel_code;  // 下单secret_code;
    protected $price_code ;  // 快递询价secret_code;
    protected $price_secret;  // 快递询价secret
    protected $check_code;  // 快递可用性查询secret_code;
    protected $secret_sign;  // 客户授权secret_sign
    protected $secret_secret;  // 客户授权secret_secret
    protected $callbackurl;  // 订阅接收接口callbackurl
    protected $type = 'kd100';  // 默认快递100
//    /**
//     *
//     */
//    public function __construct()
//    {
//            $this->key = config('kd.' . $this->type.'.key');
//            $this->secret = config('kd.' . $this->type.'.secret');
//
//            $this->secret_key = config('kd.' . $this->type.'.secret_key');
//            $this->order_code = config('kd.' . $this->type.'.order_code');
//
//            $this->price_code = config('kd.' . $this->type.'.price_code');
//            $this->price_secret = config('kd.' . $this->type.'.price_secret');
//
//            $this->check_code = config('kd.' . $this->type.'.check_code');
//            $this->cancel_code = config('kd.' . $this->type.'.cancel_code');
//
//            $this->secret_secret = config('kd.' . $this->type.'.secret_secret');
//
//            $this->secret_sign = config('kd.' . $this->type.'.secret_sign');
//            $this->callbackurl = config('kd.' . $this->type.'.callbackurl');
//    }
    /**
     *获取配置
     * @param string $name
     * @return string
     */
    public function get_kd_config($name)
    {
        $conf = config('kd.' . $this->type.'.'.$name);
        if($conf){
            return  $conf;
        }else{
            throw new \RuntimeException("快递100配置{$name}不存在！", ErrorCode::SERVER_ERROR);
        }

    }

    /**
     * 快递下单
     * @param array $param
     * @param string $order_sn
     * @return bool
     **/
    public function log($param,$order_sn='')
    {
            $send_order = DeliverySendOrder::query()->where('num',strval($param['nu']))->first(['id','order_id','order_sn','num']);
            DeliverySendOrderLog::query()->where('num',strval($param['nu']))->delete();
            $insert_arr  =[];
            if($send_order){
                $send_order = $send_order->toArray();
                foreach ($param['data'] as $key=>$value){
                    $insert_arr[] = [
                        'json_data'=>json_encode($value),
                        'time'=>$value['time'],
                        'order_id'=>$send_order['order_id'],
                        'order_sn'=>$send_order['order_sn'],
                        'status'=>$value['status'],
//                        'status_code'=>$value['statusCode'],
                        'num'=>$param['nu'],
                        'com'=>$param['com'],
                    ];
                }
            }else{
                foreach ($param['data'] as $key=>$value){
                    $insert_arr[] = [
                        'json_data'=>json_encode($value),
                        'time'=>$value['time'],
                        'status'=>$value['status'],
//                        'status_code'=>$value['statusCode'],
                        'num'=>$param['nu'],
                        'com'=>$param['com'],
                    ];
                }
            }
            if($insert_arr!=[]){
                DeliverySendOrderLog::query()->insert($insert_arr);
            }
            return true;



    }
    /**
     * 快递下单
     * @param array $params
     * @return bool
     **/
    public function c_send($params)
    {
        $params['secret_key'] = $this->get_kd_config('secret_key');
        $params['secret_code'] = $this->get_kd_config('order_code');
        $params['secret_sign'] = $this->get_kd_config('secret_sign');


        $params['cargo'] = '商品';//物品名称
        $params['weight'] = '0.5';//物品重量
        $params['remark'] = $params['remark'];//物品重量
        $params['salt'] = '';
        $params['callBackUrl'] =  $this->get_kd_config('callbackurl');
        $params['payment'] = '';
//        $params['dayType'] = '';
//        $params['pickupStartTime'] = '';
//        $params['pickupEndTime'] = '';
        $params['expType'] = '';

        $url = "http://cloud.kuaidi100.com/api";
        return json_decode(Common::request_by_curl($url,$params,2),true);
    }


    /**
     * @param $order_sn
     * @param int $type
     * @return mixed
     */
    public function delete_order($order_sn,$type=1)
    {
//        1物流  2同城
        DeliverySendOrder::where('order_sn',$order_sn)->where('service_type',$type)->delete();
    }

    /**
     * 快递下单
     * @param array $param
     * @return bool
     **/
    public function send($param)
    {
        // 参数设置
        list($msec, $sec) = explode(' ', microtime());
        $t = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);    // 当前时间戳


        // 请求参数
        $post_data = array();
        $post_data['param'] = json_encode($param, JSON_UNESCAPED_UNICODE);
        $post_data['key'] = $this->get_kd_config('key');
        $post_data['t'] = $t;
        $sign = md5($post_data['param'].$t.$this->get_kd_config('key').$this->get_kd_config('secret'));
        $post_data['sign'] = strtoupper($sign);

        $url = 'https://poll.kuaidi100.com/order/borderapi.do?method=bOrder';    // 商家寄件下单接口地址
        return json_decode(Common::request_by_curl($url,$post_data,2),true);
    }


    /**
     * 取消快递
     * @param int $order_id
     * @param string $taskId
     * @return bool
     **/
    public function cancel($order_id,$taskId=0,$msg='暂时不邮寄了')
    {
        list($msec, $sec) = explode(' ', microtime());
        $t = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);    // 当前时间戳
        $param = array (
            'taskId' => $order_id,                  // 任务ID
            'orderId' => $taskId,                 // 订单ID
            'cancelMsg' => $msg                // 取消原因，例：暂时不寄件了
        );

        // 请求参数
        $post_data = array();
        $post_data['param'] = json_encode($param, JSON_UNESCAPED_UNICODE);
        $post_data['key'] =  $this->get_kd_config('key');
        $post_data['t'] = $t;
        $sign = strtoupper(md5($post_data['param'].$t.$this->get_kd_config('key').$this->get_kd_config('secret')));
        $post_data['sign'] = strtoupper($sign);

        $url = 'https://poll.kuaidi100.com/order/borderapi.do?method=cancel';    // 商家寄件下单取消接口地址
        return json_decode(Common::request_by_curl($url,$post_data,2),true);
    }

    /**
     * 取消快递
     * @param int $order_sn
     * @param string $msg
     * @return bool
     **/
    public function c_cancel($order_sn,$msg='暂时不邮寄了')
    {
        $order_send_info = DeliverySendOrder::query()->where('order_sn',$order_sn)->orderBy('id','DESC')->first();
        if($order_send_info->state!=1){
            throw new \RuntimeException("订单状态不可拦截,仅揽收中可以拦截,state-".$order_send_info['state'], ErrorCode::SERVER_ERROR);
        }
        $post_data = array (
            'taskId' => $order_send_info->task_id,                  // 任务ID
            'orderId' => $order_send_info->delivery_order_id,                 // 订单ID
            'cancelMsg' => $msg,               // 取消原因，例：暂时不寄件了
            'secret_key' =>$this->get_kd_config('secret_key'),
            'secret_code' => $this->get_kd_config('cancel_code'),
            'secret_sign' => $this->get_kd_config('secret_sign'),
        );
        $url = 'http://cloud.kuaidi100.com/api';    // c端下单取消接口地址
        $return = [
            'code'=>200,
            'message'=>'success',
            'data'=>'取消成功',
        ];
//        $return  = json_decode(Common::request_by_curl($url,$post_data,2),true);

        if($return['code']==200){
            FlyOrder::query()->where('order_sn',$order_sn)->update([
                'delivery_id'=>0
            ]);
            $order_send_info->state = 4;
            $order_send_info->status = 2;
            $order_send_info->save();
            return true;
        }else{
            return false;
        }
    }

    public function get_send_order($order_id)
    {
       return DeliverySendOrder::query()
           ->where('order_id',$order_id)
           ->where('is_cancel',0)
           ->where('status',1)
           ->first();
    }

    public function cancel_order_info($order_id,$deduct_fee=0,$param=[])
    {
        $shop_info = CurrentShopData::getData();
        $DeliverySendOrder = new DeliverySendOrder();
        $send_order_info  =$DeliverySendOrder
            ->where('order_id',$order_id)
            ->where('delivery_type','dada')
            ->where('service_type',2)
            ->first();
        if($send_order_info->is_cancel==0){
            $send_order_info->state=4;
            $send_order_info->status=2;
            $send_order_info->is_cancel=1;
            if($param){
                $send_order_info->cancel_reason_id = $param['cancel_reason_id'];
                $send_order_info->cancel_reason = $param['cancel_reason'];
            }
            $send_order_info->deduct_fee=$deduct_fee;
            $send_order_info->save();
            DeliverySendOrder::query()->where('order_id',)->update(['state'=>4,'deduct_fee'=>$deduct_fee]);//下单记录
            FlyOrder::query()->where('order_id',$order_id)->update(['delivery_id'=>0]);//重置
            PollLog::query()->where('order_id',$order_id)->update(['delivery_id'=>0]);//订阅记录
//            //        更新余额
//            $last_money = $send_order_info->delivery_fee-$deduct_fee;
//            $FlyShopBalance = New FlyShopBalance();
//            $FlyShopBalance->where(['shop_id'=>$shop_info->id,'platform'=>1])->increment('balance',$last_money);//余额增加
//            $FlyShopBalance->where(['shop_id'=>$shop_info->id,'platform'=>1])->decrement('total_consumer',$last_money);//消费减少
        }


    }
    /**
     * 检查快递可用性
     * @param $from
     * @param $to
     * @param $check_ids
     * @return mixed
     */
    public function check($from,$to,$check_ids)
    {
        $ticket_index = "kd_check:" .$from.'-'.$to.'-'.$check_ids;
        $json_redis = $this->redis_get($ticket_index);
//        已存储的直接返回
        if($json_redis){
            return $json_redis;
        }else{
            $params = [];
            $params['secret_key'] = $this->get_kd_config('secret_key');
            $params['secret_code'] = $this->get_kd_config('check_code');
            $params['secret_sign'] =  $this->get_kd_config('secret_sign');
            $params['method'] ='line';
            $params['send'] =$from;
            $params['rec'] =$to;
            $params['com'] = $check_ids;
            $url = 'http://cloud.kuaidi100.com/api';
            $res = json_decode(Common::request_by_curl($url,$params,2),true);
//            $res = [
//                "result"=>true,
//                "message"=>"成功",
//                "data"=>[
//                    [
//                    'com'=>'shunfeng',
//                    'lsCheck'=>true,
//                    'lsCount'=>41125,
//                    'pjCheck'=>true,
//                    'xzqCode'=>440300000000,
//                    'xzqFullName'=>"广东,深圳市",
//                    ],
//                    [
//                        'com'=>'jd',
//                        'lsCheck'=>true,
//                        'lsCount'=>41125,
//                        'pjCheck'=>true,
//                        'xzqCode'=>440300000000,
//                        'xzqFullName'=>"广东,深圳市",
//                    ]
//                ],
//            ];
            $res = json_decode(json_encode($res),true);
//            查询成功的，缓存一天
            if($res&&isset($res['data'])){
                foreach($res['data'] as $key=>$value){
                    $res['data'][$key]['name']  = SELF::DELIVERY[$value['com']];
                }
                $this->redis_set($ticket_index, $res,3600*24);
            }
            return  $res;
        }
    }

    /**
     * 检查快递费用
     * @param array $param
     * @return object
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function check_price($param)
    {
        $param['weight'] = $param['weight']?$param['weight']:1;
        $ticket_index = "kd_price:" . $param['com'].'-'.$param['from'].$param['to'].$param['weight'];
        $json_redis = $this->redis_get($ticket_index);
//        $json_redis = [];
//        已存储的直接返回
        if($json_redis){
            return $json_redis;
        }else{
            $params = [];
            $params['secret_key'] = $this->get_kd_config('secret_key');
            $params['secret_code'] = $this->get_kd_config('price_code');
            $params['secret_sign'] =  $this->get_kd_config('secret_sign');
//            $params['secret_sign'] =  strtoupper(md5($this->get_kd_config('secret_key').$this->get_kd_config('price_secret')));
            $params['companyName'] =$param['com'];
            $params['sendAddr'] = $param['to'];
            $params['receiveAddr'] = $param['from'];
            $params['weight'] = $param['weight'];
            $url = 'http://cloud.kuaidi100.com/api';    // 快递可用性接口地址
            $res = json_decode(Common::request_by_curl($url,$params,2),true);
//            查询成功的，缓存一天
            if($res&&isset($res['status'])&&$res['status']==200){
                $this->redis_set($ticket_index, $res,3600*24*7);
            }
            return $res;
        }
    }

    /**
     * 订阅物流跟踪
     * @param array $param
     * @param int $send_order_sn
     * @param array $address_info
     * @return bool
     */
    public function poll($param,$send_order_sn=0,$address_info =[])
    {
        $param['parameters']['callbackurl'] = $this->get_kd_config('callbackurl');
        //订阅参数示范
//        $poll_param = array (
//            'company' => $param['kuaidicom'],          //快递公司编码
//            'number' => $res['data']['orderId'],    //快递单号
//            'from' => $param['sendManPrintAddr'],                     //出发地城市
//            'to' => $param['recManPrintAddr'],                       //目的地城市
//            'parameters' => array (
//                'callbackurl' => 'http://192.168.1.33:62002/api/v1/delivery_send/call_back',          //回调地址
//                'salt' => 'test',                 //加密串
//                'resultv2' => '1',            //行政区域解析
//                'autoCom' => '0',             //单号智能识别
//                'interCom' => '0',            //开启国际版
//                'departureCountry' => '',     //出发国
//                'departureCom' => '',         //出发国快递公司编码
//                'destinationCountry' => '',   //目的国
//                'destinationCom' => '',       //目的国快递公司编码
//                'phone' => ''                 //手机号
//            )
//        );
        $param['key']= $this->get_kd_config('key');
        //请求参数
        $post_data = array();
        $post_data["schema"] = 'json';
        $post_data["param"] = json_encode($param);

        $url = 'http://poll.kuaidi100.com/poll';    //订阅请求地址

        $params = "";
        foreach ($post_data as $k=>$v) {
            $params .= "$k=".urlencode($v)."&";     //默认UTF-8编码格式
        }
        $post_data = substr($params, 0, -1);
        $return =   json_decode(Common::request_by_curl($url,$post_data,2),true);
//        $return =[
//            'result'=>true
//        ];
        if($send_order_sn!=0){
            $order_info = FlyOrder::query()->where('order_sn',$send_order_sn)->first();
            $send_order  = [
                'service_type'=>1,
                'delivery_type'=>$param['company'],
                'delivery_name'=>self::DELIVERY[$param['company']],
                'type'=>1,
                'order_id'=>$order_info->order_id,
                'order_sn'=>$order_info->order_sn,
                'created_at'=>date('Y-m-d H:i:s'),
                'from_address'=>$address_info['street_str'].$address_info['address_info'],
                'from_name'=>$address_info['link_name'],
                'from_phone'=>$address_info['phone'],
                'to_address'=>$order_info->address,
                'to_name'=>$order_info->link_name,
                'to_phone'=>$order_info->phone,
                'send_date'=> date('Y-m-d H:i:s'),
                'num'=> $param['number'],
                'is_poll'=>1,
            ];
//            $delivery_id  = DeliverySendOrder::query()->insertGetId(Common::filter_null($send_order));
            DeliverySendOrder::query()->where('order_sn',$send_order_sn)
                ->updateOrInsert(
                    [
                        'order_id'=>$order_info->order_id,
                        'delivery_name'=>$send_order['delivery_name'],
                        'service_type'=>1,
                        'order_sn'=>$send_order_sn,
                        'type'=>1,
                        'is_poll'=>0,
                    ],
                    $send_order);
        }
        return $return;
    }


//    检查是否订阅记录
   public function check_poll(array  $params){
        $poll_info = PollLog::query()
            ->where('order_sn',$params['order_sn'])
            ->where('num',$params['num'])
            ->where('order_type',$params['order_type'])
            ->first();
       $shop_info = CurrentShopData::getData();
       $order_info = FlyOrder::query()
           ->with('with_address_info')
           ->with('with_products')
           ->where('order_sn',$params['order_sn'])->first()->toArray();
        if(!$poll_info){
            $poll_data  = [
                'order_sn'=>$params['order_sn'],
                'order_type'=>$params['order_type'],
                'com'=>$params['com'],
                'num'=>$params['num'],
                'created_at'=>date('Y-m-d H:i:s'),
            ];
            $poll_id =  PollLog::query()->where('order_sn',$params['order_sn'])->insertGetId($poll_data);
            //发货单id
            $this->sendDelivery(intval($order_info['order_id']),intval($shop_info->id),1,1,0,intval($poll_id));
        }
        return true;
    }

    public function add_log($order_id,$res)
    {
        $param = [
            'order_id'=>$order_id,
            'time'=>date('Y-m-d H:i:s'),
            'status_code'=>$res['statusCode'],
            'json_data'=>json_encode($res),
        ];
        DeliverySendOrderLog::query()->insertGetId($param);
    }


    /**
     * 发货并修改订单状态
     * @param int $order_id
     * @param int $shop_id
     * @param int $delivery_type
     * @param int $send_type 同城配送 1自行
     * @param int $send_addr_id 发货地址ID（默认商家默认地址）
     * @param int $poll_id 第三方订阅ID
     * @return bool
     */
    public function sendDelivery(int $order_id, int $shop_id, $delivery_type = 3, $send_type = 2, $send_addr_id = 0, $poll_id = 0)
    {
        try {
            // 发货
            if (!in_array($delivery_type, [ShopDeliveryConfigService::TYPE_EXPRESS, ShopDeliveryConfigService::TYPE_OWN, ShopDeliveryConfigService::TYPE_LOCAL])) {
                $delivery_type = ShopDeliveryConfigService::TYPE_LOCAL;
            }
            // 配送
            if ($delivery_type == ShopDeliveryConfigService::TYPE_LOCAL) {
                if (!in_array($send_type, [ShopDeliveryConfigService::LOCAL_SEND_OWN, ShopDeliveryConfigService::LOCAL_SEND_THIRD])) {
                    $send_type = ShopDeliveryConfigService::TYPE_OWN;
                }
            }

            $order_instance = make(FlyOrder::class)
                ->where('order_id', '=', $order_id)
                ->where('shop_id', '=', $shop_id)
                ->where('order_status', '=', FlyOrderService::STATUS_WAIT_RECEIVE)
                ->where('delivery_id', '=', 0)
                ->first();
            if (empty($order_instance)) {
                return false;
            }
            if (!empty($send_addr_id)) {
                $send_addr = $this->sendAddr->getAddrById($shop_id, $send_addr_id);
            } else {
                $send_addr = $this->sendAddr->get_default_addr($shop_id);
            }
            $addr = empty($addr) ? [] : $send_addr->toArray();
            $delivery_instance = make(FlyShopDelivery::class);
            $delivery_instance->shop_id = $shop_id;
            $delivery_instance->order_id = $order_id;
            $delivery_instance->delivery_type = $delivery_type;
            $delivery_instance->send_type = $send_type;//自行配送
            $delivery_instance->send_address = ($addr['street_str'] ?? "") . ($addr['address_info'] ?? "");
            $delivery_instance->send_link = $addr['link_name'] ?? "";
            $delivery_instance->send_phone = $addr['phone'] ?? "";
            $delivery_instance->receive_address = $order_instance->address;
            $delivery_instance->receive_link = $order_instance->link_name;
            $delivery_instance->receive_phone = $order_instance->phone;
            $delivery_instance->order_id = $order_id;
            $delivery_instance->create_time = time();
            $delivery_instance->send_time = time();
            $delivery_instance->poll_id = (int)$poll_id;
            if (!$delivery_instance->save()) {
                return false;
            }
            $order_instance->delivery_id = $delivery_instance->id;

            if($send_type==2){

            }

            $order_instance->save();

        } catch (\Throwable $exception) {
            echo $exception->getMessage();
            return false;
        }
        return true;
    }
}